from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) import csv author = 'Your name here' doc = """ Your app description """ class Constants(BaseConstants): import csv, io name_in_url = 'bangla_st3' players_per_group = 3 #Todo: Read this from some config file! #number of questions #Todo: Read this from some config file! num_rounds = int(4 / 2) #num_questions_module = int(2 / 2) #number_questions = 2 # Load question pools #Todo: Read this from some config file! B = 500 D = 100 r = 0.1 # Verbal F1 #Todo: Access same question pool (?) with io.open('bangla_st0/190910_questions.csv', "r", encoding='utf-8-sig') as questions_file: questions = list(csv.DictReader(questions_file)) class Subsession(BaseSubsession): def before_session_starts(self): pass def creating_session(self): if self.round_number == 1: self.session.vars['app3_initialised'] = False # and to randomize differently for each participant, you could use # the random.sample technique, but assign into participant.vars # instead of session.vars. # for p in self.get_players(): # question_data = p.current_question_type(p.participant.vars['next_role']) # p.question_id = int(question_data['id']) # p.question = question_data['question'] # p.solution = question_data['solution'] # #Should be constant and equal to p.participant.vars['next_role'] # p.qtype = int(question_data['type']) def on_app_start(self): import json, random #Only initilise once per session if self.session.vars['app3_initialised'] == True: return None print("[MAIN]/t/tReshuffeling Questions!") self.session.vars['questions'] = Constants.questions.copy() type1_questions = [q for q in Constants.questions if q['type'] == '1'] type2_questions = [q for q in Constants.questions if q['type'] == '2'] randomized_questions1 = random.sample(type1_questions, Constants.num_rounds ) randomized_questions2 = random.sample(type2_questions, Constants.num_rounds ) self.session.vars['questions_task1_1'] = randomized_questions1 self.session.vars['questions_task1_2'] = randomized_questions2 print("RND pool for 1", self.session.vars['questions_task1_1']) print("RND pool for 2", self.session.vars['questions_task1_2']) print("--------RND pool for 1", self.session.vars['questions_task1_1']) print("--------RND pool for 2", self.session.vars['questions_task1_2']) print('[MAIN]\t\tInitialising App 3...') self.session.vars['app3_initialised'] = True # for p in self.get_players(): # p.matchedPlayer = p.participant.vars['next_match'] # p.myRole = p.participant.vars['next_role'] # p.uid = p.participant.vars['this_uid'] #lOAD questions to participant based on participant.this_uid for p in self.get_players(): print(p.participant.vars['this_uid'],p.participant.vars['next_match'],p.participant.vars['next_role'] ) #role_select = p.choose_questions(p.participant.vars['next_role']) #print("function returns:", p.choose_questions( p.participant.vars['next_role']) ) #p.participant.vars['task1_questions'] = role_select #print("participant vars:", p.participant.vars['task1_questions'] ) p.matchedPlayer = p.participant.vars['next_match'] p.myRole = p.participant.vars['next_role'] p.uid = p.participant.vars['this_uid'] #print(p.participant.vars['task1_questions']) #Load first question into player p.get_next_question(p.participant.vars['next_role']) def production_function(self): print('[MAIN]\t\tRunning production function...') #Move this to participant too! productions = {} revenues = {} for p in self.get_players(): #Back-fill player data player_in_all_rounds = p.in_all_rounds() #Because every round/question initialises new player for pp in player_in_all_rounds: pp.matchedPlayer = p.participant.vars['next_match'] pp.myRole = pp.participant.vars['next_role'] pp.uid = pp.participant.vars['this_uid'] for p in self.get_players(): if p.matchedPlayer != -1: #is matched print("matched pl", p.matchedPlayer,) other_perf = None for op in self.get_players(): print(op.uid, p.matchedPlayer) if op.uid == p.matchedPlayer: other_perf = op.get_performance() print("other perf", other_perf) self_perf = p.get_performance() p.partner_performance = other_perf print(p.uid, self_perf, other_perf) # # # # PRODUCTION HERE p.production = self_perf * other_perf * 2 * Constants.B productions[p.uid] = p.production # # # # CAPITAL STRUCTURE p.debt_repayment = (1+Constants.r) * Constants.D p.revenue = p.production - (1+Constants.r) * Constants.D revenues[p.uid] = p.revenue else: # is UNmatched self_perf = p.get_performance() print(p.uid, self_perf) # # # # PRODUCTION HERE p.production = self_perf * 1 * Constants.B productions[p.uid] = p.production # # # # CAPITAL STRUCTURE HERE p.debt_repayment = (1+Constants.r) * Constants.D p.revenue = p.production - (1+Constants.r) * Constants.D revenues[p.uid] = p.revenue print(productions, revenues) #self.session.vars['productions'] = productions #self.session.vars['revenues'] = revenues def migrate_to_session(self): # move all relevant subsession variables to the session level to keep info on app switch print('[MAIN]\t\tMigrating App3 variables') # ! # ! # ! # Participant/session vars are not recorded and lost after end of the experiod! # SUBSESSION -> SESSION # PLAYER -> PARTICIPANT for p in self.get_players(): p.participant.vars['performance'] = p.performance p.participant.vars['partner_performance'] = p.partner_performance p.participant.vars['production'] = p.production p.participant.vars['revenue'] = p.revenue p.participant.vars['debt_repayment'] = p.debt_repayment def back_up(self): if self.session.vars['do_backups'] == False: return None import smtplib, ssl, time, json this_savepoint_id = 'svpt0301' save_data = [] for p in self.get_players(): this_row = [] # save metadata: date, player uid, player otree id, this_app this_row.append( time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()) ) this_row.append( p.uid) this_row.append( p.participant.id_in_session ) this_row.append( p.participant.code ) this_row.append('app3') # save content: this_row.append([ p.participant.vars['performance'], p.participant.vars['partner_performance'] , p.participant.vars['production'], p.participant.vars['revenue'], p.participant.vars['debt_repayment'] , ]) save_data.append(this_row) save_data.append([ self.session.vars['megaRound'], self.session.vars['questions_task1_1'], self.session.vars['questions_task1_2'] ]) try: this_dat = json.dumps(save_data) message = str(this_savepoint_id) + "\n " + this_dat from_address = "bangladeshi.experimentor@gmail.com" password = "shakespear66" context = ssl.create_default_context() with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server: server.login(from_address, password) server.sendmail( from_address, "bangladeshi.experimentor@gmail.com", message) except: print("ERR message not sent") #Todo: Record how answered each question? class Group(BaseGroup): pass class Player(BasePlayer): uid = models.IntegerField() matchedPlayer = models.IntegerField() myRole = models.IntegerField() performance = models.FloatField() partner_performance = models.FloatField() production = models.FloatField() revenue = models.FloatField() debt_repayment = models.FloatField() question_id = models.IntegerField() question = models.StringField() solution = models.StringField() qtype = models.IntegerField() qsubtype = models.IntegerField() questions = models.StringField() this_question_data = models.StringField() submitted_answer = models.StringField(widget=widgets.RadioSelect) def submitted_answer_choices(self): import json #print("choosing questions:", self.participant.vars['this_uid'],self.participant.vars['next_match'],self.participant.vars['next_role'] ) #print(self.participant.vars['task1_questions']) #question_data = self.participant.vars['task1_questions'] #Has to be round - 2 because skips rounds where other stage!!! print("Round", self.round_number) if self.participant.vars['next_role'] == 1: self.questions = json.dumps( self.session.vars['questions_task1_1'] ) print("choosing questions:", self.session.vars['questions_task1_1']) #return self.session.vars['questions_task1_1'] elif self.participant.vars['next_role'] == 2: self.questions = json.dumps( self.session.vars['questions_task1_2'] ) print("choosing questions:", self.session.vars['questions_task1_1']) #return self.session.vars['questions_task1_2'] question_data = json.loads(self.questions) qd = question_data[self.round_number - 1] print("question data submitted: ", qd) #Todo: Randomise order of choices but don't forget solution! if int(qd['type']) == 1: return [ qd['choice1'], qd['choice2'], qd['choice3'], qd['choice4'], ] elif int(qd['type']) == 2: return [ qd['choice1'], qd['choice2'], #qd['choice3'], ] is_correct = models.BooleanField() # def current_question_type(self, qtype): # if qtype == 1: # return self.session.vars['questions1'][self.round_number - 1] # elif qtype == 2: # return self.session.vars['questions2'][self.round_number - 1] def check_correct(self): self.is_correct = (self.submitted_answer == self.solution) def get_next_question(self, role): import json if role == 1: self.questions = json.dumps( self.session.vars['questions_task1_1'] ) print("choosing questions:", self.session.vars['questions_task1_1']) #return self.session.vars['questions_task1_1'] elif role == 2: self.questions = json.dumps( self.session.vars['questions_task1_2'] ) print("choosing questions:", self.session.vars['questions_task1_1']) #return self.session.vars['questions_task1_2'] question_data = json.loads(self.questions) question_data = question_data[self.round_number - 1] self.question_id = int(question_data['id']) self.question = question_data['question'] self.solution = question_data['solution'] #Should be constant and equal to p.participant.vars['next_role'] self.qtype = int(question_data['type']) self.qsubtype = int(question_data['subtype']) def get_performance(self): player_in_all_rounds = self.in_all_rounds() # print( [p.is_correct for p in player_in_all_rounds if int(p.qtype) == 1] ) if self.myRole == 1: self.performance = sum([p.is_correct for p in player_in_all_rounds if int(p.qtype) == 1]) elif self.myRole == 2: self.performance = sum([p.is_correct for p in player_in_all_rounds if int(p.qtype) == 2]) # Convert to percentage self.performance = round( self.performance / Constants.num_rounds ,ndigits=2 ) print("PERFO", self.uid, self.performance) return self.performance ## def choose_questions(self, role): ## import json ## if role == 1: # self.questions = json.dumps( self.session.vars['questions_task1_1'] ) # print("choosing questions:", self.session.vars['questions_task1_1']) # return self.session.vars['questions_task1_1'] # elif role == 2: # self.questions = json.dumps( self.session.vars['questions_task1_2'] ) # print("choosing questions:", self.session.vars['questions_task1_1']) # return self.session.vars['questions_task1_2'] def update_score(self): self.participant.vars['score'] = max([self.participant.vars['score'] + self.revenue, 0]) return self.participant.vars['score']